iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 21
0

抽象工廠類別

有了冒險者之後,他們還需要各種裝備。假如一個冒險者需要武器、頭盔、上衣、褲子、鞋子5種裝備, 村莊內又有4種不同專業的冒險者,這樣我們就要建立20種工廠類別來生產裝備,而且每增加一種冒險者類別, 就要多增加5個實體工廠類別,如果使用剛才的工廠模式來管理生產裝備,實體工廠類別就會變非常得多,程式碼會很雜亂不易維護。 這時候工廠模式不能解決我們的問題,因此這邊改變一下工廠的定義,首先工廠仍然只是一個抽象介面(Factory),但是介面規定工廠現在生產的不是一種產品, 而是生產一個冒險者類別一系列所有的裝備,也就是說一間工廠要生產武器、頭盔、上衣、褲子、鞋子5種裝備(Product), 當然有了抽象工廠介面後當然也需要實體工廠(ConcreteFactory),例如說鬥士裝備生產工廠就會生產一系列的鬥士裝備(ConcreteProduct) ,這就是抽象工廠模式。 我們現在假設一個冒險者只有武器與上衣兩種裝備。

  • 抽象類別上衣。
  • 子類別:
    1.盔甲
    2.皮衣
//上衣介面(Product)
abstract class Clothes {
    var def: Int = 0   // 防禦力

    //展示這件衣服
    abstract fun displayMyClothes():String
}

 //盔甲(ConcreteProduct)-鬥士上衣
class Armor : Clothes(){
     override fun displayMyClothes() = "盔甲,防禦力${def}"
 }

//皮衣(ConcreteProduct)-弓箭手上衣
class Leather : Clothes(){
    override fun displayMyClothes() = "皮衣,防禦力${def}"
}
  • 抽象類別武器。
    子類別:
    1.弓箭
    2.長劍
//武器介面(Product)
 abstract class Weapon {
     var atk: Int = 0        // 攻擊力
     var range: Int = 0   // 攻擊範圍

    //展示武器
     abstract fun displayMyWeapon():String
}


 //長劍(ConcreteProduct)-鬥士武器
class LongSword : Weapon(){
     override fun displayMyWeapon() = "長劍,攻擊力${atk},範圍${range}"

 }


//弓(ConcreteProduct)-弓箭手武器
class Bow : Weapon(){
    override fun displayMyWeapon() = "弓箭,攻擊力${atk},範圍${range}"
}
  • 生產裝備的工廠抽象介面。
  • 子類別:
    1.專門生產鬥士裝備的工廠
    2.專門生產弓箭手裝備的工廠
//裝備工廠介面(Factory)-定義每一間工廠應該生產哪些東西
interface EquipFactory {
    //製造武器
    fun getWeapon(): Weapon
    //製造衣服
    fun getClothes(): Clothes
}


//生產鬥士裝備的工廠
object WarriorEquipFactory : EquipFactory {

    override fun getWeapon(): Weapon {
        val product = LongSword()
        product.atk = 10
        product.range = 1
        return product
    }

    override fun getClothes(): Clothes {
        val product = Armor()
        product.def = 10
        return product
    }

}

//生產弓箭手裝備的工廠
object ArcherEquipFactory : EquipFactory {

    override fun getWeapon(): Weapon {
        val product = Bow()
        product.atk = 10
        product.range = 10
        return product
    }

    override fun getClothes(): Clothes {
        val product = Leather()
        product.def = 5
        return product
    }

}
  • 冒險者抽象介面。
  • 子類別:
    1.鬥士
    2.弓箭手
interface Adventurer {
    val type: String
    val weapon: Weapon    //武器
    val clothes: Clothes   //衣服
    fun introduceMySelf():String
}

// 弓箭手
class Archer : Adventurer {
    override val type = "我是弓箭手"
    override val clothes = ArcherEquipFactory.getClothes()
    override val weapon = ArcherEquipFactory.getWeapon()
    override fun introduceMySelf() = "${type}。${clothes.displayMyClothes()};${weapon.displayMyWeapon()}"

}

// 鬥士
class Warrior : Adventurer {
    override val type = "我是鬥士"
    override val clothes = WarriorEquipFactory.getClothes()
    override val weapon =  WarriorEquipFactory.getWeapon()
    override fun introduceMySelf() = "${type}。${clothes.displayMyClothes()};${weapon.displayMyWeapon()}"
}
  • 培訓冒險者的訓練營(生成冒險者的工廠)
  • 子類別:
    1.培訓鬥士的訓練營
    2.培訓弓箭手的訓練營
interface TrainingCamp{
    fun trainAdventurer():Adventurer
}

object ArcherTrainingCamp:TrainingCamp {
    override fun trainAdventurer(): Adventurer {

        println("訓練一個弓箭手")
        return Archer()

    }
}

object WarriorTrainingCamp:TrainingCamp {
    override fun trainAdventurer(): Adventurer{

        println("訓練一個鬥士")
        return Warrior()
    }
}
  • 執行層
val archer = ArcherTrainingCamp.trainAdventurer()
    println(archer.introduceMySelf())

    val warrior = WarriorTrainingCamp.trainAdventurer()
    println(warrior.introduceMySelf())
  • 執行結果
訓練一個弓箭手
我是弓箭手。皮衣,防禦力5;弓箭,攻擊力10,範圍10
訓練一個鬥士
我是鬥士。盔甲,防禦力10;長劍,攻擊力10,範圍1

總結

  • 簡單工廠模式:
    1.工廠直接負責管理所有的產品,利用if else 或 switch case判斷式來產生產品。
    2.在產品種類不多的小型專案中使用較為方便。
    3.違反開閉原則。
  • 工廠模式:
    1.工廠提升為一個概念,實際上產生產品的他的子類別實體工廠。注重在"一個工廠生產一種產品",例如弓箭手訓練營只要負責生產弓箭手。
    2.完全符合開閉原則。
  • 抽像工廠模式:
    1.抽像工廠模式加入了新的概念,轉而注重在產品與產品間的關係,像武器與衣服本來是扯不上關係的兩種物品,但都是屬於同一種冒險者的裝備,因此他們就有了這層關係。所以一個工廠生產的會是該。
    2.部分符合開閉原則。當要新增一個產品系列的時候,符合開閉原則中開放擴充的特性。但要修改某產品系列中的某項產品時,違反了封閉修改的原則,因為有可能會影響到同系列的其他產品。

工廠模式最大的好處就是,三種模式皆符合單一職責原則,分工明確,而使用者使用產品時不需理解產品是如何產生的。

更加封閉了應該封閉的地方,也更加放寬了應該開放讓使用者自定義的地方,也更加分離了各自類別必須獨立負責的事。

參考資料

工廠模式


上一篇
Android x Kotlin: 工廠模式淺解[上]
下一篇
MVVM架構與data binding [上]
系列文
Android Kotlin開發 -小嫩雞的30篇精選筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言